﻿using System;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using System.Collections.ObjectModel;
using BankCharts.Silverlight.ViewModel.Models;
using System.Collections.Generic;
using System.Globalization;

namespace BankCharts.Silverlight.ViewModel.SubViewModel
{
    public class UnparsedBankDataManagerVM : ViewModelBase
    {
        private CultureInfo USCulture = new CultureInfo("en-US");
        private CultureInfo FRCulture = new CultureInfo("fr-FR");

        #region CSVContent
        private string _CSVContent = string.Empty;

        /// <summary>
        /// Gets the CSVContent property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public string CSVContent
        {
            get
            {
                return _CSVContent;
            }

            set
            {
                if (_CSVContent == value)
                {
                    return;
                }

                _CSVContent = value;

                // Update bindings, no broadcast
                RaisePropertyChanged("CSVContent");
            }
        }
        #endregion

        /// <summary>
        /// Parse the entire content and return all lines. Not parsed yet.
        /// </summary>
        /// <returns></returns>
        private List<BankLine> ProcessInLines()
        {
            string[] lines = CSVContent.Split('\r', '\n');
            List<BankLine> resultLines = new List<BankLine>(lines.Length);
            foreach (var line in lines)
            {
                if (!string.IsNullOrWhiteSpace(line))
                {
                    BankLine temp = new BankLine() { NotParsedBankLine = line };
                    temp.SplitedColumn = temp.NotParsedBankLine.Split(';');
                    resultLines.Add(temp);
                }
            }
            return resultLines;
        }


        public List<BankLine> Initialize(out int nbTotalLines, out int nbValidLines)
        {
            List<BankLine> lines = ProcessInLines();
            Random r = new Random(DateTime.Now.Millisecond);

            Dictionary<int, int> dateEnWeight = new Dictionary<int, int>();
            Dictionary<int, int> dateFrWeight = new Dictionary<int, int>();
            Dictionary<int, int> valueWeight = new Dictionary<int, int>();
            Dictionary<int, int> textWeight = new Dictionary<int, int>();

            for (int j = 0; j < lines.Count; j++)
            {
                //int index = r.Next(lines.Count);
                int columnMaxIndex = lines[j].SplitedColumn.Count();
                for (int i = 0; i < columnMaxIndex; i++)
                {
                    DateTime date;
                    float value;
                    //Date en
                    if (DateTime.TryParse(lines[j].SplitedColumn[i], USCulture, DateTimeStyles.None, out date))
                    {
                        AddVote(dateEnWeight, i);
                    }
                    //Date Fr
                    if (DateTime.TryParse(lines[j].SplitedColumn[i], FRCulture, DateTimeStyles.None, out date))
                    {
                        AddVote(dateFrWeight, i);
                    }
                    //Value
                    if (float.TryParse(lines[j].SplitedColumn[i], out value))
                    {
                        AddVote(valueWeight, i);
                    }
                    //Text
                    AddVote(textWeight, i, lines[j].SplitedColumn[i].Count());
                }
            }

            int indexDateEnWeight = WhichIndexHaveHigher(dateEnWeight);
            int indexDateFrWeight = WhichIndexHaveHigher(dateFrWeight);
            int indexValueWeight = WhichIndexHaveHigher(valueWeight);
            int indexTextWeight = WhichIndexHaveHigher(textWeight);

            bool IsUSCulture = false;
            //There is more US date ?
            if (dateFrWeight.Count > 0 && dateEnWeight.Count > 0)
            {
                IsUSCulture = dateEnWeight[indexDateEnWeight] > dateFrWeight[indexDateFrWeight];
            }
            return ProcessEachLines(lines, IsUSCulture ? indexDateEnWeight : indexDateFrWeight, indexValueWeight, indexTextWeight, IsUSCulture,out nbTotalLines,out nbValidLines);
        }

        private int WhichIndexHaveHigher(Dictionary<int, int> dic)
        {
            int result = 0;
            int higherValue = Int32.MinValue;
            foreach (var item in dic)
            {
                if (item.Value > higherValue)
                {
                    higherValue = item.Value;
                    result = item.Key;
                }
            }
            return result;
        }

        private void AddVote(Dictionary<int, int> votes, int index, int value = 1)
        {
            if (!votes.Keys.Contains(index))
            {
                votes.Add(index, 0);
            }
            votes[index] += value;
        }

        private List<BankLine> ProcessEachLines(List<BankLine> initLines, int indexDate, int indexValue, int indexText, bool IsUSDateFormat, out int nbTotalLines, out int nbValidLines)
        {
            List<BankLine> lines = initLines;

            nbTotalLines = 0;
            nbValidLines = 0;

            foreach (var line in lines)
            {
                nbTotalLines++;
                string[] itemsInLine = line.NotParsedBankLine.Split(';');
                if (itemsInLine.Length >= 4)
                {
                    line.Text = itemsInLine[indexText];
                    DateTime date;
                    float value;
                    if (DateTime.TryParse(itemsInLine[indexDate], IsUSDateFormat ? USCulture : FRCulture, DateTimeStyles.None, out date) &&
                        float.TryParse(itemsInLine[indexValue], out value))
                    {
                        line.Date = date;
                        line.Value = value;
                        line.IsValid = true;
                        nbValidLines++;
                    }
                }
            }


            return lines.Where(c => c.IsValid).ToList();
        }
    }
}
